/**
 * @author [siwi]
 * @email [siwi@siwi.me]
 * @create date 2017-09-18 02:44:10
 * @modify date 2017-09-18 02:44:10
 * @desc [siwi Oauth ]
*/

const Client = require('../../mongooses/oauth/Client')
const AccessToken = require('../../mongooses/oauth/AccessToken')
const RefreshToken = require('../../mongooses/oauth/RefreshToken')
const Code = require('../../mongooses/oauth/Code')
const User = require('../../mongooses/rbac/User')
const Jwt = require('../../lib/Jwt')
class AuthorizeController {
    constructor() {

    }
    async test () {
        return 100;
    }
    /**
     * token
     * 
     * @param {any} ctx 
     * @param {any} next 
     * @memberof OauthController
     */
    async token(ctx, next) {
        let grant_type = ctx.request.body.grant_type //生成token的类型  authorization_code password refresh_token
        if (grant_type == 'authorization_code') {
            let data = {
                client_id: ctx.request.body.client_id,
                client_secret: ctx.request.body.client_secret,
                redirect_uri: ctx.request.body.redirect_uri,
                code: ctx.request.body.code
            }
           
        }
        if (grant_type == 'password') {
            let data = {
                client_id: ctx.request.body.client_id,
                client_secret: ctx.request.body.client_secret,
                username: ctx.request.body.username,
                password: ctx.request.body.password,
                scope: ctx.request.body.scope,
            }
            let user = await User.check_password(data.username, data.password)

            if (!user) {
                ctx.throw('用户名或密码错误')
            }
    
            // client
            let client = await Client.findById(data.client_id)
    
            if (!client) {
                ctx.throw('客户端不存在')
            }
    
            if (client.secret != data.client_secret) {
                ctx.throw('秘钥错误')
            }

            let expires_at =  Math.floor(Date.now() / 1000) + 86400 // access_token 1天 refresh_token 2天 单位毫秒
            
            // access-token加密数据
            let sign_access_token = {
                exp: expires_at,
                data:{
                    username: user.username,
                    created: user.created,
                    city: user.username,
                    gender: user.gender,
                    avatar: user.avatar,
                    display_name: user.display_name,
                    id: user.id
                }
            }
            // 生成token access_token
            let access_token = await Jwt.sign(sign_access_token)
           
            let access_token_data = {
                user_id: user.id,
                client_id: client.id,
                access_token: access_token,
                name: user.username,
                scopes: client.scopes,
                revoked: 0,
                expires_at: expires_at * 1000,
            }
            let access_token_res = await AccessToken.create(access_token_data)

            // 刷新令牌数据
            let sign_refresh_token = {
                exp: expires_at + 86400,    // 刷新令牌多一天
                data:{
                    access_token_id: access_token_res.id,
                    user_id: user.id,
                    client_id: client.id
                }
            }
            let refresh_token = await Jwt.sign(sign_refresh_token)
        
            ctx.body = {
                ret: 0,
                msg: 'OK',
                data: {
                    access_token: access_token_res.access_token,
                    refresh_token: refresh_token,
                    expires_at: access_token_res.expires_at
                }
            }
        }
        // refresh_token 
        if (grant_type == 'refresh_token') {
            let refresh_token = ctx.request.body.refresh_token

            let decode = await Jwt.verify(refresh_token)

            if (!decode) {
                ctx.throw('refresh_token 错误')
            }

            let time = Date.now()   // 毫秒
            let exp = decode.exp    // 过期时间 秒
            
            if (time > exp * 1000) {
                ctx.throw('refresh_token 过期')
            }
            
            let data = decode.data
            let access_token_id = data.access_token_id
            let client_id = data.client_id
            
            let token = await AccessToken.findById({'_id': access_token_id})

            let token_decode = await Jwt.verify(token.access_token)

            // 判断access_token 是否过期 未过期 返回原样 已过期从新生成
            if (token_decode.exp * 1000 > Date.now()) {
                console.log('yes')
                ctx.body = {
                    ret: 0,
                    msg: 'OK',
                    data: {
                        access_token: token.access_token,
                        refresh_token: refresh_token,
                        expires_at: token.expires_at
                    }
                }
                return next()
            } else {
                let user = await User.findById({'_id': token.user_id})
                
                let expires_at =  Math.floor(Date.now() / 1000) + 86400 // access_token 1天 refresh_token 2天 单位毫秒
                
                // access-token加密数据
                let sign_access_token = {
                    exp: expires_at,
                    data:{
                        username: user.username,
                        created: user.created,
                        city: user.username,
                        gender: user.gender,
                        avatar: user.avatar,
                        display_name: user.display_name,
                        id: user.id
                    }
                }
                // 生成token access_token
                let new_access_token = await Jwt.sign(sign_access_token)
               
                let access_token_data = {
                    user_id: user.id,
                    client_id: client_id,
                    access_token: new_access_token,
                    name: user.username,
                    revoked: 0,
                    expires_at: expires_at * 1000,
                }
                let access_token_res = await AccessToken.create(access_token_data)
                
                // 刷新令牌数据
                let sign_refresh_token = {
                    exp: expires_at + 86400,    // 刷新令牌多一天
                    data:{
                        access_token_id: access_token_res.id,
                        user_id: user.id,
                        client_id: client_id
                    }
                }
                // 保存刷新记录
                await RefreshToken.create({
                    access_token: token.access_token, // 过期的token
                    refresh_token: refresh_token      // 传入的刷新token
                })

                let new_refresh_token = await Jwt.sign(sign_refresh_token)
    
                ctx.body = {
                    ret: 0,
                    msg: 'OK',
                    data: {
                        access_token: access_token_res.access_token,
                        refresh_token: new_refresh_token,
                        expires_at: access_token_res.expires_at
                    }
                }
                return next()
            }
        }
    }

    async code (ctx, next) {
        ctx.body = 'token'
    }
    /**
     * 
     * 获取用户
     * 
     * @param {any} ctx 
     * @param {any} next 
     * @returns 
     * @memberof AuthorizeController
     */
    async user (ctx, next) {
       let oauth = ctx.oauth
       let user = User.findById({'_id': ctx.oauth.id})

       if (user) {
           ctx.body = {
               ret: 0,
               msg: 'OK',
               data: {
                   user: user
               }
           }
           return next()
       } else {
            ctx.body = {
                ret: -1,
                msg: 'not find',
            }
       }
    }
}
module.exports = new AuthorizeController()